/***************************************************************************
 *   Copyright (C) 2008 by Eduardo Gurgel Pinho                            *
 *   edgurgel@gmail.com                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/

#include "material_panel.h"

#include "color_widget.h"

#include "object/object.h"
#include "material/material.h"
#include "material/light_material.h"
#include "material/object_material.h"
#include "material/color_material.h"
#include "material/texture_material.h"
#include "common/color.h"
#include "qtimage.h"

#include <QLabel>
#include <QPushButton>
#include <QDoubleSpinBox>
#include <QMenu>
#include <QAction>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QFileDialog>
#include <QImage>


namespace Ui {

Material_Panel::Material_Panel(QWidget* _parent) : QWidget(_parent) , material(0) , workaround(0) {  
	object_text = new QLabel*[4];
	
	QVBoxLayout* vboxlayout= new QVBoxLayout();
	for(unsigned short i = 0;i<4;i++) {
		object_text[i] = new QLabel();
		object_colors[i] = new Color_Widget();
		QHBoxLayout* hlayout = new QHBoxLayout();
		hlayout->addWidget(object_text[i]);
		hlayout->addStretch();
		hlayout->addWidget(object_colors[i]);
		vboxlayout->addLayout(hlayout);
	}
	
	object_text[0]->setText(tr("Ambient"));
	object_text[1]->setText(tr("Diffuse"));
	object_text[2]->setText(tr("Specular"));
	object_text[3]->setText(tr("Reflectiveness"));
	
	QHBoxLayout* hlayout = new QHBoxLayout();
	brightness_label = new QLabel(tr("Brightness"));
	brightness_spinbox = new QDoubleSpinBox();
	brightness_spinbox->setMinimum(0.1);
	brightness_spinbox->setMaximum(127.0);
	brightness_spinbox->setReadOnly(true);
	hlayout->addWidget(brightness_label);
	hlayout->addStretch();
	hlayout->addWidget(brightness_spinbox);
	
	vboxlayout->addLayout(hlayout);
	
	/* Light_Material */
	light_text = new QLabel("Light color");
	light_color = new Color_Widget();
	QHBoxLayout* llayout = new QHBoxLayout();
	llayout->addWidget(light_text);
	llayout->addStretch();
	llayout->addWidget(light_color);
	light_color->hide();
	light_text->hide();
	
	vboxlayout->addLayout(llayout);	
	
	QHBoxLayout* elayout = new QHBoxLayout();
	energy_label = new QLabel(tr("Energy"));
	energy_spinbox = new QDoubleSpinBox();
	energy_spinbox->setMinimum(0.1);
	energy_spinbox->setMaximum(255.0);
	energy_spinbox->setReadOnly(true);
	elayout->addWidget(energy_label);
	elayout->addStretch();
	elayout->addWidget(energy_spinbox);
	
	energy_spinbox->hide();
	energy_label->hide();
	
	vboxlayout->addLayout(elayout);	
	
	/* Texture_Material */
	texture_text = new QLabel(tr("Texture"));
// 	texture_image = new QLabel();
	
	/* Change Object_Material */
	change_button = new QPushButton(tr("Change Material"));
	change_menu = new QMenu(change_button);
	QAction* color_menu_item = new QAction(tr("Color"),change_menu);
	QAction* texture_menu_item = new QAction(tr("Texture"),change_menu);
	change_menu->addAction(color_menu_item);
	change_menu->addAction(texture_menu_item);
	change_button->setMenu(change_menu);
	connect(color_menu_item,SIGNAL(triggered(bool)),this,SLOT(color_material()));
	connect(texture_menu_item,SIGNAL(triggered(bool)),this,SLOT(texture_material()));
	
	vboxlayout->addWidget(change_button);
	change_button->hide();
	
	vboxlayout->addStretch();
	this->setLayout(vboxlayout);
}


Material_Panel::~Material_Panel(void) { 
	delete[] object_colors;
	delete light_color;
	delete brightness_spinbox;
}

QSize Material_Panel::minimumSizeHint() const {
	return QSize(200,100);
}

void Material_Panel::select_material(Sirat::Material::Material* _material) {
	material = _material;
	switch(material->get_type()) {
		case Sirat::Material::Color_Material_Type: {
			Sirat::Material::Color_Material* color_material = static_cast<Sirat::Material::Color_Material*>(material);
			
			Sirat::Common::Color ambient = color_material->get_ambient();
			Sirat::Common::Color diffuse = color_material->get_diffuse() ;
			Sirat::Common::Color specular = color_material->get_specular() ;
			Sirat::Common::Color reflectiveness = color_material->get_reflectiveness() ;
			double brightness = color_material->get_brightness();
			
			if(object_colors[0]) object_colors[0]->set_color(ambient);
			if(object_colors[1]) object_colors[1]->set_color(diffuse);
			if(object_colors[2]) object_colors[2]->set_color(specular);
			if(object_colors[3]) object_colors[3]->set_color(reflectiveness);
			
			brightness_spinbox->setReadOnly(false);
			brightness_spinbox->setValue(brightness);			
			
			for(unsigned short i = 0;i<4;i++) {
				object_text[i]->show();
				object_colors[i]->show();
			}
			brightness_spinbox->show();
			brightness_label->show();
			
			light_color->hide();
			light_text->hide();
			energy_spinbox->hide();
			energy_label->hide();
			
			change_button->show();
			
			disconnect(light_color,SIGNAL(color_updated()),this,SLOT(update_material()));
			
			connect(object_colors[0],SIGNAL(color_updated()),this,SLOT(update_material()));
			connect(object_colors[1],SIGNAL(color_updated()),this,SLOT(update_material()));
			connect(object_colors[2],SIGNAL(color_updated()),this,SLOT(update_material()));
			connect(object_colors[3],SIGNAL(color_updated()),this,SLOT(update_material()));
			connect(brightness_spinbox,SIGNAL(valueChanged(double)),this,SLOT(update_material()));
			connect(energy_spinbox,SIGNAL(valueChanged( double )),this,SLOT(update_material()));
			
			break;
		}
		case Sirat::Material::Light_Material_Type: {
			Sirat::Material::Light_Material* light_material = static_cast<Sirat::Material::Light_Material*>(material);
			Sirat::Common::Color color = light_material->get_color();
			double energy = light_material->get_energy();
			
			if(light_color) light_color->set_color(color);
			energy_spinbox->setReadOnly(false);
			energy_spinbox->setValue(energy);
			
			for(unsigned short i = 0;i<4;i++) {
				object_text[i]->hide();
				object_colors[i]->hide();
			}
			brightness_spinbox->hide();
			brightness_label->hide();
			
			light_color->show();
			light_text->show();
			energy_spinbox->show();
			energy_label->show();
			
			disconnect(object_colors[0],SIGNAL(color_updated()),this,SLOT(update_material()));
			disconnect(object_colors[1],SIGNAL(color_updated()),this,SLOT(update_material()));
			disconnect(object_colors[2],SIGNAL(color_updated()),this,SLOT(update_material()));
			disconnect(object_colors[3],SIGNAL(color_updated()),this,SLOT(update_material()));
			disconnect(brightness_spinbox,SIGNAL(valueChanged(int)),this,SLOT(update_material()));
			
			connect(light_color,SIGNAL(color_updated()),this,SLOT(update_material()));
			connect(energy_spinbox,SIGNAL(valueChanged( double )),this,SLOT(update_material()));
			
			break;
		}
		default: {
			break;
		}
	}
	
}

void Material_Panel::select_object(Sirat::Object::Object* _object) {
	workaround = _object;
}

void Material_Panel::color_material(void) {
	if(workaround != 0) {
		
		
		
	}
}

void Material_Panel::texture_material(void) {
	if(workaround != 0) {
		QString filename = QFileDialog::getOpenFileName(this,tr("Save Image as"), QDir::currentPath(),tr("Image Files (*.png)"));
		if (!filename.isNull()) {
			QImage test(filename);
			
			Qtimage* image = new Qtimage(test.width(),test.height());
			image->load_file(filename.toStdString().c_str());
			Sirat::Material::Texture_Material* texture_material = new Sirat::Material::Texture_Material(image,Sirat::Common::Color(0.5,0.5,0.5));
			
			workaround->set_material(texture_material);
		}
	}		
}

void Material_Panel::clear(void) {
	material = 0;
	
	for(unsigned int i = 0 ; i < 4; i++) {
		object_colors[i]->clear();
	}
	light_color->clear();
		
	disconnect(object_colors[0],SIGNAL(color_updated()),this,SLOT(update_material()));
	disconnect(object_colors[1],SIGNAL(color_updated()),this,SLOT(update_material()));
	disconnect(object_colors[2],SIGNAL(color_updated()),this,SLOT(update_material()));
	disconnect(object_colors[3],SIGNAL(color_updated()),this,SLOT(update_material()));
	disconnect(brightness_spinbox,SIGNAL(valueChanged(int)),this,SLOT(update_brightness(int)));
	disconnect(light_color,SIGNAL(color_updated()),this,SLOT(update_material()));	
	
	brightness_spinbox->setReadOnly(true);
}

void Material_Panel::update_material(void) {
	if(material != 0) {
		switch(material->get_type()) {
			case Sirat::Material::Color_Material_Type: {
				Sirat::Material::Color_Material* color_material = static_cast<Sirat::Material::Color_Material*>(material);
				color_material->set_ambient(object_colors[0]->get_color());
				color_material->set_diffuse(object_colors[1]->get_color());
				color_material->set_specular(object_colors[2]->get_color());
				color_material->set_reflectiveness(object_colors[3]->get_color());
				color_material->set_brightness(brightness_spinbox->value());
				break;
			}
			case Sirat::Material::Light_Material_Type: {
				Sirat::Material::Light_Material* light_material = static_cast<Sirat::Material::Light_Material*>(material);
				
				light_material->set_color(light_color->get_color());
				light_material->set_energy(energy_spinbox->value());
				
				break;
			}
			default: {
				break;
			}
		}
	}
}
}



